#include <ltypes.h>
#include <lmacros.h>
#include <ltriMesh.h>
#include <lcollisionDetector.h>
#include <lcollisionResult.h>

LLIB_BEGIN

template <typename BVTree_t>
void geom::SceneObj<BVTree_t>::Init(std::vector<Vec3f>& vertexList, std::vector<Vec3i>& faceVertexIndexList)
{
    /* build up mesh */
    _mesh.SetModelData(vertexList, faceVertexIndexList);

    /* build up tree */
    _tree.Init(_mesh);

    /* set up collision flag */
    _collision = vector<Boolean>(_mesh.GetFaceNum(), FALSE);
}

template <typename BVTree_t>
void geom::SceneObj<BVTree_t>::UpdateTree()
{
    BVTree_t::Iter* iter = _tree.CreateIter(BVTree_t::Iter::Postorder);
    BVTree_t::BVNode* node = iter->Next();
    while(node != NULL) {
        node->Update();
        node = iter->Next();
    }
    delete iter;
}

template <typename BVTree_t>
void geom::SceneObj<BVTree_t>::CollisionDetect( SceneObj<BVTree_t>& first, SceneObj<BVTree_t>& second )
{
    // prepare data store
    collision::CollisionResult cr;
    std::fill(first._collision.begin(),first._collision.end(),FALSE);
    std::fill(second._collision.begin(),second._collision.end(),FALSE);

    // the collision process
    BVTree_t* firstRoot = first._tree.GetRoot();
    BVTree_t* secondRoot = second._tree.GetRoot();
    collision::CollisionDetector::CollisionDetect(firstRoot, secondRoot, &cr);

    // update _collision
    Int32 faceNum = first._mesh.GetFaceNum();
    FOR(F,0,faceNum) {
        if(cr.CheckCollide(first._mesh.GetFace(F)))
            first._collision[F] = TRUE;
    }
    faceNum = second._mesh.GetFaceNum();
    FOR(F,0,faceNum) {
        if(cr.CheckCollide(second._mesh.GetFace(F)))
            second._collision[F] = TRUE;
    }
}

template <typename BVTree_t>
void geom::SceneObj<BVTree_t>::SelfCollisonDetect( SceneObj<BVTree_t>& obj )
{
    // prepare data store
    collision::CollisionResult cr;
    fill(obj._collision.begin(),obj._collision.end(),FALSE);

    // the collision process
    collision::CollisionDetector::SelfCollisionDetect(obj._tree.GetRoot(), &cr);

    // update _collision
    Int32 faceNum = obj._mesh.GetFaceNum();
    FOR(F,0,faceNum) {
        if(cr.CheckCollide(obj._mesh.GetFace(F)))
            obj._collision[F] = TRUE;
    }
}

LLIB_END
